﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

using Moq;
using SharpTestsEx;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using DomusDotNet.Sbm.Client.SL4.ViewModels;
using DomusDotNet.Sbm.Client.SL4.Services;
using System.Security.Principal;
using DomusDotNet.Sbm.Client.SL4.Infrastructure;
using DomusDotNet.Sbm.Client.SL4.WCFServices;
using System.Collections.ObjectModel;
using Caliburn.Micro;

namespace DomusDotNet.Sbm.Client.SL4.Tests
{

    [TestClass]
    public class the_LoginViewModel : TestBase
    {

        [TestMethod]
        public void should_disallow_login_when_no_username_is_provided()
        {
            var sut = new LoginViewModel(null)
            {
                Password = "some_password"
            };

            sut.CanLogin.Should().Be.False();
        }

        [TestMethod]
        public void should_disallow_login_when_no_password_is_provided()
        {
            var sut = new LoginViewModel(null)
            {
                Username = "some_user"
            };

            sut.CanLogin.Should().Be.False();
        }

        [TestMethod]
        public void should_allow_login_when_username_and_password_are_provided()
        {
            var sut = new LoginViewModel(null)
            {
                Username = "some_user",
                Password = "some_password"
            };

            sut.CanLogin.Should().Be.True();
        }


        [TestMethod]
        public void should_call_service_with_provided_credentials()
        {
            var sut = new LoginViewModel(null)
            {
                Username = "some_user",
                Password = "some_password"
            };

            TestExecutorFor(sut.Login())
                .Next<WCFServiceCallResult>(x =>
                {
                    x.Should().Not.Be.Null();
                    x.Request.Should().Be.OfType<LoginRequest>();

                    x.GetRequest<LoginRequest>().UserName
                        .Should().Be.EqualTo("some_user");

                    x.GetRequest<LoginRequest>().Password
                        .Should().Be.EqualTo("some_password");
                });

        }

        [TestMethod]
        public void should_show_message_on_failed_login()
        {
            var sut = new LoginViewModel(null)
            {
                Username = "some_user",
                Password = "some_password"
            };

            TestExecutorFor(sut.Login())
                .Next<WCFServiceCallResult>(x =>
                {
                    x.Response = new LoginResponse
                    {
                        Result = false,
                        Errors = new ObservableCollection<Error>{ 
                            new Error{ Message = "error1"} ,
                            new Error{ Message = "error2"} 
                        }
                    };
                })
                .Finish();

            sut.ErrorMessage.Should().Be.EqualTo("error1\nerror2");
        }


        [TestMethod]
        public void should_send_event_on_succesful_login()
        {
            var conductor = new Mock<IConductor>();
            var eventAggregator = new Mock<IEventAggregator>();
            
            var sut = new LoginViewModel(eventAggregator.Object)
            {
                Username = "some_user",
                Password = "some_password",
                Parent = conductor.Object
            };

            TestExecutorFor(sut.Login())
                .Next<WCFServiceCallResult>(x =>
                {
                    x.Response = new LoginResponse { Result = true , SessionGUID= Guid.NewGuid().ToString()};
                })
                .Finish();

            sut.ErrorMessage.Should().Be.NullOrEmpty();
            eventAggregator.Verify(
                x => x.Publish(
                    It.Is<object>(e => ((LoggedInEvent)e).Principal.Identity.Name == "some_user"),
                    null
                )
            );


        }
 
    }
}
